package uk.ac.sanger.das.dasregistry.springrest.sources;

import java.util.Date;
import java.util.List;

import org.apache.log4j.Logger;
import org.biodas.jdas.dassources.utils.RegistrySourceAdapter;
import org.biodas.jdas.schema.lastmodified.LASTMODIFIED;
import org.biodas.jdas.schema.registry.capabilities.CAPABILITIES;
import org.biodas.jdas.schema.servers.SERVERS;
import org.biodas.jdas.schema.sources.SOURCE;
import org.biodas.jdas.schema.sources.SOURCES;


public class SourcesCache extends Thread implements Runnable, DasSourceManager{
	SOURCES das1sources;
	Date lastUpdate;//last time data was updated
	DasSourceDao dasSourceDao;
	private SOURCES sourcesCache;
	private long pause=300000;//default pause is 5 minute between cache updates but this can be overriden in the spring config
	
	Logger logger=Logger.getLogger(SourcesCache.class);

	public SourcesCache(DasSourceDao dasSourceDao){
		this.dasSourceDao=dasSourceDao;
		
	}
	
	
	
	public void run( ) {
        for (;;) {
            
            try {
                Thread.sleep(10000);
                this.getAllSources();
            } catch (InterruptedException ie) {
            	ie.printStackTrace();
                return;
            }
        }
    }



	@Override
	public SOURCES getAllSources() {
		java.util.Date lastMod = dasSourceDao.getLastModified();
		//logger.warn("pinging last update in sources cache pause="+pause);
		logger.debug("lastModified in sources cache="+lastMod);
		if (timeToUpdate(lastMod, lastUpdate, pause)) {
			refreshCache();
		}
		return sourcesCache; 
	}



	private synchronized  void refreshCache() {
		logger.warn("sources cache is refreshing from dao");
		sourcesCache=dasSourceDao.getAllDasSources();
		lastUpdate=new Date(System.currentTimeMillis());
	}


	public boolean timeToUpdate(Date lastMod, Date lastUpdate, long pause){
		if (sourcesCache == null || lastUpdate==null){
			logger.warn("lastupdate or sources cache is null so we update");
			return true;
		}
		logger.debug("lastmod="+lastMod.toString());
		logger.debug("lastUpdate="+lastUpdate.toString());
		logger.debug("pause seconds="+pause/1000);
		//if lastmodified is after last update we want to update, but we need a delay in cases of mirroring 
		//so we need to add a delay
		Date delay=null;
		if(lastUpdate!=null){
			delay=new Date(lastUpdate.getTime()+pause);
		}
		Date now=new Date(System.currentTimeMillis());
		if (now.after(delay)&&lastMod.after(lastUpdate)){
			logger.warn("-----------------------------need to update sources--------------------------");
			return true;
		}
		 return false;
	}
	@Override
	public synchronized SOURCES add(SOURCES sources) throws DasSourceNotRegisterableExcepton {
		sourcesCache.getSOURCE().add(sources.getSOURCE().get(0));
		return null;
	}



	@Override
	public synchronized void activate(String sourceUri) {
		//remove the inactive property from this cached source if it has one
		List<SOURCE> sourcesList=sourcesCache.getSOURCE();
		for(int i=0; i<sourcesList.size();i++){
			SOURCE source1=sourcesList.get(i);
			
			if(source1.getUri().equals(sourceUri)){
				RegistrySourceAdapter ra=new RegistrySourceAdapter(source1);
				ra.setActive();//activate the source
			}
		}
		
	}



	@Override
	public synchronized void delete(String sourceUri) {
		logger.warn("delete in cache sourceUri="+sourceUri);
		for(SOURCE source:sourcesCache.getSOURCE()){
			if(source.getUri().equals(sourceUri)){
				logger.warn("removing source from cache "+source.getUri());
				sourcesCache.getSOURCE().remove(source);
			}
		}
		
	}



	@Override
	public synchronized SOURCES update(SOURCES source) {
		SOURCE updatedSource=source.getSOURCE().get(0);
		List<SOURCE> sourcesList=sourcesCache.getSOURCE();
		for(int i=0; i<sourcesList.size();i++){
			SOURCE source1=sourcesList.get(i);
			
			if(source1.getUri().equals(updatedSource.getUri())){
				sourcesList.set(i, updatedSource);
			}
		}
		return null;
	}



	@Override
	public LASTMODIFIED getLastModified() {
		//  Auto-generated method stub
		return null;
	}



	@Override
	public SERVERS getServers() {
		//  Auto-generated method stub
		return null;
	}



	@Override
	public CAPABILITIES getKnownCapabilities() {
		//  Auto-generated method stub
		return null;
	}
}
